#include <iostream>
#include <math.h>
#include <limits.h>
#include "ALU_DEF.h"
#include "ALU_MUL.h"

using namespace std;

ALU_MUL::ALU_MUL()
{
	Ready = true;
	inputA = 0;
	inputB = 0;
	outputZ = 0;
	OpCode = NOP_OPCODE;
	CyclesLeft = 0;
}

void ALU_MUL::update()
{
	long long int temp = 0;
	unsigned long long int temp2= 0;
	unsigned int temp3 = 0;

	if(Ready)
	{
		if( NOP_OPCODE != OpCode )
		{
			switch (OpCode)
			{
			case IMUL_OPCODE:
				CyclesLeft = IMUL_DELAY;
				break;
			case UMUL_OPCODE:
				CyclesLeft = UMUL_DELAY;
				break;
			case IMULR_OPCODE:
				CyclesLeft = IMULR_DELAY;
				break;
			case UMULR_OPCODE:
				CyclesLeft = UMULR_DELAY;
				break;
			case IMULD_OPCODE:
				CyclesLeft = IMULD_DELAY;
				break;
			case UMULD_OPCODE:
				CyclesLeft = UMULD_DELAY;
				break;
			case FMUL_OPCODE:
				CyclesLeft = FMUL_DELAY;
				break;
			}

			Ready = false;
			update();
		}
	}
	else // Not ready, processing operation
	{
		CyclesLeft--;

		if( 0 == CyclesLeft )
		{
			switch( OpCode )
			{
				case IMUL_OPCODE:
					outputZ = inputA * inputB;
					break;
				case UMUL_OPCODE:
					outputZ = (unsigned int) inputA * (unsigned int) inputB;
					break;
				case IMULR_OPCODE:
					outputZ = inputA * inputB;
					break;
				case UMULR_OPCODE:
					outputZ = (unsigned int) inputA * (unsigned int) inputB;
					break;
				case IMULD_OPCODE:
					outputZ = ((unsigned int )inputA & 0x0000FFFF) * ((unsigned int) inputB & 0x0000FFFF);
					if (((inputA < 0) && (inputB >= 0)) || ((inputA >= 0) && (inputB < 0)))
						outputZ = outputZ * -1;
					break;
				case UMULD_OPCODE:
					outputZ = ((unsigned int) inputA & 0x0000FFFF) * ((unsigned int) inputB & 0x0000FFFF);
					break;
				case FMUL_OPCODE:
					outputFZ = inputFA * inputFB;
					break;
			}

			Ready = true;
		}
	}
}

int ALU_MUL::getOutput()
{
	return outputZ;
}

float ALU_MUL::getOutputF()
{
	return outputFZ;
}

bool ALU_MUL::isReady()
{
	return Ready;
}
